package generateConnections;

import java.awt.Color;
import java.util.ArrayList;

import exception.NoConnectionPossibleException;

import networkInterface.NetworkInterfaceBase;

import logging.Logger;

import object.Connection;
import object.Node;
import util.NodeUtil;

public class ConnectNetworks extends GenerateConnectionBase 
{
	private int test = 0;
	
	@Override
	public void genConnections(ArrayList<Node> nodes, Node node) 
	{
		Logger.getInstance().log(Logger.TRACE, "Looking to combine networks");
		if( test == 1) node.color = Color.red;
		
		// Get a trace of the network this node can reach
		ArrayList<Node> myNetwork = new ArrayList<Node>();
		NodeUtil.mapNetwork(node, myNetwork);
		Logger.getInstance().log(Logger.TRACE, "Number of nodes in the network: " + myNetwork.size());
		
		// Find all of the nodes that the node could connect to
		ArrayList<Node> possibleConnections = new ArrayList<Node>();
		for( NetworkInterfaceBase baseInterface: node.getInterfaces() )
		{
			for( NetworkInterfaceBase possibleInterface : baseInterface.getPossiblyConnectableInterfaces(nodes))
			{
				Node hold = possibleInterface.getNode(); //holds the node of the current possilbe interface
				ArrayList<Node> pwndNode = new ArrayList<Node>(); //This will hold the node that we removed the connection from in order to create a new connection
				
				//If hold is in the current network, we do not need to worry about forcing a connection
				if( myNetwork.contains(hold) ) 
					continue;
				else if( baseInterface.canConnect(possibleInterface) )
				{
					try 
					{
						baseInterface.addConnection(possibleInterface);
					} 
					catch (IllegalStateException e1) 
					{
						// TODO Auto-generated catch block
						e1.printStackTrace();
					} 
					catch (NoConnectionPossibleException e1) 
					{
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}
				else 
				{
					if( test == 1 ) hold.color = Color.green;
					Logger.getInstance().log(Logger.TRACE, baseInterface.canConnectWithReason(possibleInterface));
					if( baseInterface.canConnectWithReason(possibleInterface).equalsIgnoreCase("No connections left") )
					{
						if( test == 1 ) hold.color = Color.orange;
						
						//Remove connection from target interface
						ArrayList<Connection> connections = possibleInterface.getConnections();
						if( !connections.isEmpty() ) 
						{
							Logger.getInstance().log(Logger.TRACE, "Removing connection from target interface");
							Connection target = connections.get(0);
							if( target.getN1() == hold ) pwndNode.add(target.getN2());
							else pwndNode.add(target.getN1());
							possibleInterface.removeConnection(target);
						}
						else
							Logger.getInstance().log(Logger.TRACE, "Currently no connections on target interface");
						
						//Remove connection from base interface
						connections.clear();
						connections = baseInterface.getConnections();
						if( !connections.isEmpty() )
						{
							Logger.getInstance().log(Logger.TRACE, "Removing connection from base interface");
							Connection target = connections.get(0);
							if( target.getN1() == hold ) pwndNode.add(target.getN2());
							else pwndNode.add(target.getN1());
							baseInterface.removeConnection(target);
						}
						else
							Logger.getInstance().log(Logger.TRACE, "Currently no connections on base interface");
						
						//Create a connection between the two
						try { 
							baseInterface.addConnection(possibleInterface);
							Logger.getInstance().log(Logger.TRACE, "Creating a new connection between networks");
						} 
						catch (IllegalStateException e) {
							Logger.getInstance().log(Logger.WARNING, "We have reached a rather unpleasant state");
						}
						catch (NoConnectionPossibleException e) 
						{
							Logger.getInstance().log(Logger.WARNING, "Could not create a new connection with the node");							
						}
						GenerateShortestConnection gen = new GenerateShortestConnection();
						for( Node pwnd: pwndNode )
							gen.genConnections(nodes, pwnd);
						NodeUtil.mapNetwork(node, myNetwork);
						
					}
						
						
					
					possibleConnections.add(hold);
				}
			}
		}
		
		
		
		
		Logger.getInstance().log(Logger.TRACE, "Leaving combine Networks");
	}
	
	
}
